﻿using System.Collections.Generic;
using CTEM.Models;
using CTEM.Controllers.DAO;
using System;
using CTEM.Controllers.Global;

namespace CTEM.Controllers.BUS
{
    public class ConstructionBUS
    {
        /// <summary>
        /// 
        /// </summary>
        private readonly CS_ConstructionDAO _consDAO = new CS_ConstructionDAO();

        /// <summary>
        /// 
        /// </summary>
        private readonly CS_EstimateExpensesDAO _estexpDAO = new CS_EstimateExpensesDAO();

        /// <summary>
        /// 
        /// </summary>
        private readonly CS_SubcontractorDAO _subconDAO = new CS_SubcontractorDAO();

        private readonly CS_SubcontractorContractDAO _subcontractDAO = new CS_SubcontractorContractDAO();


        #region Business Layer for Construction Entity 
        /// <summary>
        /// Validate all Properties of Construction Object before Add or Edit it
        /// </summary>
        /// <param name="cons">Construction was sent from user</param>
        /// <param name="errorMessage">Message will out when has property not validate</param>
        /// <param name="fieldName">Return field name of error Property</param>
        /// <returns></returns>
        public bool ValidateConstruction(CS_ConstructionDTO cons, out string errorMessage, out string fieldName)
        {
            cons.ConstructionName = Global.Global.TitleCase(cons.ConstructionName);
            cons.ConstructionName = Global.Global.RemoveRedundantSpace(cons.ConstructionName);
            if (cons.ConstructionName.Equals(Constants.EMPTY_TEXT))
            {
                errorMessage = "Bạn Chưa Nhập Tên Công Trình";
                fieldName = "ConstructionName";
                return false;
            }
            else if (cons.ConstructionName.Length > 125)
            {
                errorMessage = "Tên Công Trình Không Được Dài Quá 125 Ký Tự";
                fieldName = "ConstructionName";
                return false;
            }
            else if (cons.ContractValues == 0)
            {
                errorMessage = "Bạn Chưa Nhập Giá Trị Hợp Đồng";
                fieldName = "ContractValues";
                return false;
            }
            else if (cons.ConstructionType.Equals(Constants.EMPTY_TEXT))
            {
                errorMessage = "Bạn Chưa Nhập Loại Công Trình";
                fieldName = "ConstructionType";
                return false;
            }
            else if (!cons.ConstructionType.Equals(CS_ConstructionDTO.CONSTRUCTION_MASONRY) &&
                        !cons.ConstructionType.Equals(CS_ConstructionDTO.CONSTRUCTION_IRRIGATION))
            {
                errorMessage = "Loại Công Trình Không Hợp Lệ";
                fieldName = "ConstructionType";
                return false;
            }
            else if (cons.CommencementDate > cons.CompletionDate)
            {
                errorMessage = "Ngày Hoàn Thành Không Thể Nhỏ Hơn Ngày Khởi Công";
                fieldName = "CompletionDate";
                return false;
            }
            else if (cons.ManagerID == 0)
            {
                errorMessage = "Bạn Chưa Nhập Người Quản Lý Công Trình";
                fieldName = "ManagerID";
                return false;
            }
            else if (cons.Status.Equals(Constants.EMPTY_TEXT))
            {
                errorMessage = "Bạn Chưa Nhập Tình Trạng Của Công Trình";
                fieldName = "Status";
                return false;
            }
            else if (!cons.Status.Equals(CS_ConstructionDTO.NEW_CONSTRUCTION) &&
                        !cons.Status.Equals(CS_ConstructionDTO.WORKING_CONSTRUCTION) &&
                        !cons.Status.Equals(CS_ConstructionDTO.CANCEL_CONSTRUCTION) && 
                        !cons.Status.Equals(CS_ConstructionDTO.FINISHED_CONSTRUCTION))
            {
                errorMessage = "Tình Trạng Của Công Trình Không Hợp Lệ";
                fieldName = "Status";
                return false;
            }
            else if (cons.ProgressRate < 0 || cons.ProgressRate > 1)
            {
                errorMessage = "Tiến Độ Của Công Trình Phải Từ 0% Đến 100%";
                fieldName = "ProgressRate";
                return false;
            }
            else if (cons.ProgressRate > 0 && cons.Status.Equals(CS_ConstructionDTO.NEW_CONSTRUCTION))
            {
                errorMessage = "Tiến Độ Của Công Trình Mới Phải Bằng 0%";
                fieldName = "ProgressRate";
                return false;
            }
            else if (cons.ProgressRate < 1 && cons.Status.Equals(CS_ConstructionDTO.FINISHED_CONSTRUCTION))
            {
                errorMessage = "Tiến Độ Của Công Trình Hoàn Thành Phải Bằng 100%";
                fieldName = "ProgressRate";
                return false;
            }
            else if (!cons.ConstructionName.Equals(Constants.EMPTY_TEXT))
            {
                List<CS_ConstructionDTO> listcon = LoadConstruction(false);
                foreach (var item in listcon)
                {
                    if (item.ConstructionName.Equals(cons.ConstructionName) && item.ConstructionID != cons.ConstructionID)
                    {
                        errorMessage = "Tên Công Trình Bạn Vừa Nhập Đã Tồn Tại";
                        fieldName = "ConstructionName";
                        return false;
                    }
                }
            }   
            errorMessage = Constants.EMPTY_TEXT;
            fieldName = Constants.EMPTY_TEXT;
            return true;
        }      

        /// <summary>
        /// 
        /// </summary>
        /// <param name="isactive"></param>
        /// <returns></returns>
        public List<CS_ConstructionDTO> LoadConstruction(bool isactive)
        {
            return _consDAO.LoadAllConstructions(isactive);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="consID"></param>
        /// <returns></returns>
        public CS_ConstructionDTO GetConstructionByID(long consID)
        {
            return _consDAO.GetConstructionByID(consID);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="cons"></param>
        /// <returns></returns>
        public long CreateConstruction(CS_ConstructionDTO cons)
        {
            cons.ConstructionName = Global.Global.TitleCase(cons.ConstructionName);
            cons.ConstructionName = Global.Global.RemoveRedundantSpace(cons.ConstructionName);
            long consID = _consDAO.CreateConstruction(cons);
            if (consID != 0)
            {
                WarehouseBUS warehouseBUS = new WarehouseBUS();
                long success1 = 0;
                long success2 = 0;
                cons.ConstructionID = consID;
                success1 = CreateEstimateExpenses(GenerateEstimate(cons));
                success2 = warehouseBUS.CreateWarehouse(GenerateConstructionWarehouse(cons));
                if (success1 == 0 || success2 == 0)
                {
                    DeleteConstruction(consID);
                    consID = 0;
                }
            }
            return consID;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="cons"></param>
        /// <returns></returns>
        public bool UpdateConstruction(CS_ConstructionDTO cons)
        {
            cons.ConstructionName = Global.Global.TitleCase(cons.ConstructionName);
            cons.ConstructionName = Global.Global.RemoveRedundantSpace(cons.ConstructionName);
            cons.UpdatedBy = Global.Global.CurrentUser.Username;
            cons.LastUpdated = DateTime.Today;
            return _consDAO.UpdateConstruction(cons);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="consID"></param>
        /// <returns></returns>
        public bool DeleteConstruction(long consID)
        {
            return _consDAO.DeleteConstruction(consID);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="cons"></param>
        /// <returns></returns>
        private CS_EstimateExpensesDTO GenerateEstimate(CS_ConstructionDTO cons)
        {
            CS_EstimateExpensesDTO genEst = new CS_EstimateExpensesDTO() 
            {
                ConstructionID = cons.ConstructionID,
                ConstructionType = cons.ConstructionType
            };
            return genEst;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="cons"></param>
        /// <returns></returns>
        private WH_WarehouseDTO GenerateConstructionWarehouse(CS_ConstructionDTO cons)
        {
            WH_WarehouseDTO genWH = new WH_WarehouseDTO()
            {
                WarehouseName = String.Format("Kho Công Trình: {0}", cons.ConstructionName),
                ConstructionID = cons.ConstructionID,
                Address = cons.ConstructionAddress,
                Description = String.Format("Đây là kho hàng của công trình: {0}", cons.ConstructionName)                
            };
            return genWH;
        }
        #endregion

        #region Business Layer for EstimateExpenses Entity
        /// <summary>
        /// 
        /// </summary>
        /// <param name="estexp"></param>
        /// <returns></returns>
        public long CreateEstimateExpenses(CS_EstimateExpensesDTO estexp)
        {
            return _estexpDAO.CreateEstimateExpenses(estexp);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="estexpID"></param>
        /// <returns></returns>
        public bool DeleteEstimateExpenses(long estexpID)
        {
            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="isactive"></param>
        /// <returns></returns>
        internal List<CS_EstimateExpensesDTO> LoadEstimateEspenses(bool isactive)
        {
            return _estexpDAO.LoadAllEstimateExpenses(isactive);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="estDTO"></param>
        /// <returns></returns>
        internal bool UpdateEstimateExpenses(CS_EstimateExpensesDTO estDTO)
        {
            estDTO.UpdatedBy = Global.Global.CurrentUser.Username;
            estDTO.LastUpdated = DateTime.Today;
            return _estexpDAO.UpdateEstimateExpenses(estDTO);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="estexpID"></param>
        /// <returns></returns>
        internal CS_EstimateExpensesDTO GetEstimateExpensesByID(long estexpID)
        {
            return _estexpDAO.LoadEstimateExpensesByConstructionID(estexpID);
        }
        #endregion

        #region Business Layer for EstimateDetail Entity
        public bool ValidateEstimateDetail(CS_EstimateDetailDTO estdt, out string errorMessage, out string fieldName)
        {
            errorMessage = "";
            fieldName = "";
            return true;
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="estexp"></param>
        /// <returns></returns>
        public long CreateEstimateDetail(CS_EstimateDetailDTO estexp)
        {
            return _estexpDAO.CreateEstimateDetail(estexp);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="estdtID"></param>
        /// <returns></returns>
        public bool DeleteEstimateDetail(long estdtID)
        {
            return _estexpDAO.DeleteEstimateDetail(estdtID);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="isactive"></param>
        /// <returns></returns>
        internal List<CS_EstimateDetailDTO> LoadEstimateDetail(long isactive)
        {
            return _estexpDAO.LoadEstimateDetail(isactive);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="estDTO"></param>
        /// <returns></returns>
        internal bool UpdateEstimateDetail(CS_EstimateDetailDTO estDTO)
        {
            return _estexpDAO.UpdateEstimateDetail(estDTO);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="estdtID"></param>
        /// <returns></returns>
        internal CS_EstimateDetailDTO GetEstimateDetailByID(long estdtID)
        {
            return _estexpDAO.LoadEstimateDetailByID(estdtID);
        }
        #endregion

        #region Business Layer for Subcontractor Entity
        /// <summary>
        /// 
        /// </summary>
        /// <param name="subconDTO"></param>
        /// <param name="errorMessage"></param>
        /// <param name="fieldName"></param>
        /// <returns></returns>
        public bool ValidateSubcontractor(CS_SubcontractorDTO subconDTO, out string errorMessage, out string fieldName)
        {
            subconDTO.SubcontractorName = Global.Global.TitleCase(subconDTO.SubcontractorName);
            subconDTO.SubcontractorName = Global.Global.RemoveRedundantSpace(subconDTO.SubcontractorName);
            if (subconDTO.SubcontractorName.Equals(Constants.EMPTY_TEXT))
            {
                errorMessage = "Bạn Chưa Nhập Tên Nhà Thầu";
                fieldName = "SubcontractorName";
                return false;
            }
            else if (subconDTO.SubcontractorName.Length > 50)
            {
                errorMessage = "Tên Nhà Thầu Không Được Dài Quá 50 Ký ";
                fieldName = "SubcontractorName";
                return false;
            }
            else if (subconDTO.SubcontractorName.Equals(Constants.EMPTY_TEXT))
            {
                List<CS_SubcontractorDTO> listsubcon = LoadSubcontractor(false);
                foreach (var item in listsubcon)
                {
                    if (item.SubcontractorName.Equals(subconDTO.SubcontractorName))
                    {
                        errorMessage = "Tên Nhà Thầu Bạn Vừa Nhập Đã Tồn Tại";
                        fieldName = "SubcontractorName";
                        return false;
                    }
                }
            }
            errorMessage = "";
            fieldName = "";
            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="subconDTO"></param>
        /// <returns></returns>
        public long CreateSubcontractor(CS_SubcontractorDTO subconDTO)
        {
            subconDTO.SubcontractorName = Global.Global.TitleCase(subconDTO.SubcontractorName);
            subconDTO.SubcontractorName = Global.Global.RemoveRedundantSpace(subconDTO.SubcontractorName);
            return _subconDAO.CreateSubcontractor(subconDTO);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="subconID"></param>
        /// <returns></returns>
        public bool DeleteSubcontractor(long subconID)
        {
            return _subconDAO.DeleteSubcontractor(subconID);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="isactive"></param>
        /// <returns></returns>
        internal List<CS_SubcontractorDTO> LoadSubcontractor(bool isactive)
        {
            return _subconDAO.LoadAllSubcontractors(isactive);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="subconDTO"></param>
        /// <returns></returns>
        internal bool UpdateSubcontractor(CS_SubcontractorDTO subconDTO)
        {
            subconDTO.UpdatedBy = Global.Global.CurrentUser.Username;
            subconDTO.LastUpdated = DateTime.Today;
            subconDTO.SubcontractorName = Global.Global.TitleCase(subconDTO.SubcontractorName);
            subconDTO.SubcontractorName = Global.Global.RemoveRedundantSpace(subconDTO.SubcontractorName);
            return _subconDAO.UpdateSubcontractor(subconDTO);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="subconID"></param>
        /// <returns></returns>
        internal CS_SubcontractorDTO GetSubcontractorByID(long subconID)
        {
            return _subconDAO.GetSubcontractorByID(subconID);
        }
        #endregion

        #region Business Layer for SubcontractorContract Entity
        /// <summary>
        /// 
        /// </summary>
        /// <param name="subconDTO"></param>
        /// <param name="errorMessage"></param>
        /// <param name="fieldName"></param>
        /// <returns></returns>
        public bool ValidateSubcontractorContract(CS_SubcontractorContractDTO subconDTO, out string errorMessage, out string fieldName)
        {
            subconDTO.WorkItem = Global.Global.TitleCase(subconDTO.WorkItem);
            subconDTO.WorkItem = Global.Global.RemoveRedundantSpace(subconDTO.WorkItem);
            if (subconDTO.WorkItem.Equals(Constants.EMPTY_TEXT))
            {
                errorMessage = "Bạn Chưa Nhập Tên Hạng Mục";
                fieldName = "WorkItem";
                return false;
            }
            else if (subconDTO.WorkItem.Length > 50)
            {
                errorMessage = "Tên Hạng Mục Phải Bé Hơn 50 Ký Tự";
                fieldName = "WorkItem";
                return false;
            }
            else if (subconDTO.ConstructionID == 0)
            {
                errorMessage = "Bạn Chưa Nhập Chọn Công Trình";
                fieldName = "ConstructionID";
                return false;
            }
            else if (subconDTO.SubcontractorID == 0)
            {
                errorMessage = "Bạn Chưa Chọn Nhà Thầu";
                fieldName = "SubcontrartorID";
                return false;
            }
            else if (!subconDTO.WorkItem.Equals(Constants.EMPTY_TEXT))
            {
                List<CS_SubcontractorContractDTO> listsubcontract = LoadSubcontractorContract(0, 0,false);
                foreach (var item in listsubcontract)
                {
                    if (item.WorkItem.Equals(subconDTO.WorkItem) && 
                            item.ConstructionID == subconDTO.ConstructionID && 
                            item.SubcontractorID == subconDTO.SubcontractorID)
                    {
                        errorMessage = "Tên Hạng Mục Bạn Vừa Nhập Đã Tồn Tại";
                        fieldName = "WorkItem";
                        return false;
                    }
                }
            }
            else if (subconDTO.ContractValues == 0)
            {
                errorMessage = "Bạn Chưa Nhập Giá Trị Hợp Đồng";
                fieldName = "ContractValues";
                return false;
            }
            else if (subconDTO.CommencementDate > subconDTO.CompletionDate)
            {
                errorMessage = "Ngày Hoàn Thành Không Thể Nhỏ Hơn Ngày Khởi Công";
                fieldName = "CompletionDate";
                return false;
            }
            else if (subconDTO.Status.Equals(Constants.EMPTY_TEXT))
            {
                errorMessage = "Bạn Chưa Nhập Tình Trạng Của Hạng Mục";
                fieldName = "Status";
                return false;
            }
            else if (!subconDTO.Status.Equals(CS_ConstructionDTO.NEW_CONSTRUCTION) &&
                        !subconDTO.Status.Equals(CS_ConstructionDTO.WORKING_CONSTRUCTION) &&
                        !subconDTO.Status.Equals(CS_ConstructionDTO.CANCEL_CONSTRUCTION) &&
                        !subconDTO.Status.Equals(CS_ConstructionDTO.FINISHED_CONSTRUCTION))
            {
                errorMessage = "Tình Trạng Của Công Trình Không Hợp Lệ";
                fieldName = "Status";
                return false;
            }
            else if (subconDTO.ProgressRate < 0 || subconDTO.ProgressRate > 100)
            {
                errorMessage = "Tiến Độ Của Công Trình Phải Từ 0% Đến 100%";
                fieldName = "ProgressRate";
                return false;
            }
            else if (subconDTO.ProgressRate > 0 && subconDTO.Status.Equals(CS_ConstructionDTO.NEW_CONSTRUCTION))
            {
                errorMessage = "Tiến Độ Của Công Trình Mới Phải Bằng 0%";
                fieldName = "ProgressRate";
                return false;
            }
            else if (subconDTO.ProgressRate < 100 && subconDTO.Status.Equals(CS_ConstructionDTO.FINISHED_CONSTRUCTION))
            {
                errorMessage = "Tiến Độ Của Công Trình Hoàn Thành Phải Bằng 100%";
                fieldName = "ProgressRate";
                return false;
            }
            errorMessage = Constants.EMPTY_TEXT;
            fieldName = Constants.EMPTY_TEXT;
            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="subconDTO"></param>
        /// <returns></returns>
        public long CreateSubcontractorContract(CS_SubcontractorContractDTO subconDTO)
        {
            subconDTO.WorkItem = Global.Global.TitleCase(subconDTO.WorkItem);
            subconDTO.WorkItem = Global.Global.RemoveRedundantSpace(subconDTO.WorkItem);
            return _subcontractDAO.CreateSubcontractorContract(subconDTO);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="subconID"></param>
        /// <returns></returns>
        public bool DeleteSubcontractorContract(long subconID)
        {
            return _subcontractDAO.DeleteSubcontractorContract(subconID);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="isactive"></param>
        /// <returns></returns>
        internal List<CS_SubcontractorContractDTO> LoadSubcontractorContract(long consID, long subconID, bool isactive)
        {
            return _subcontractDAO.LoadAllSubcontractorContracts(consID, subconID, isactive);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="subconDTO"></param>
        /// <returns></returns>
        internal bool UpdateSubcontractorContract(CS_SubcontractorContractDTO subconDTO)
        {
            subconDTO.UpdatedBy = Global.Global.CurrentUser.Username;
            subconDTO.LastUpdated = DateTime.Today;
            subconDTO.WorkItem = Global.Global.TitleCase(subconDTO.WorkItem);
            subconDTO.WorkItem = Global.Global.RemoveRedundantSpace(subconDTO.WorkItem);
            return _subcontractDAO.UpdateSubcontractorContract(subconDTO);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="subconID"></param>
        /// <returns></returns>
        internal CS_SubcontractorContractDTO GetSubcontractorContractByID(long subconID)
        {
            return _subcontractDAO.GetSubcontractorContractByID(subconID);
        }
        #endregion

        #region Business Layer for ConstructionProgress Entity
        /// <summary>
        /// 
        /// </summary>
        /// <param name="subconDTO"></param>
        /// <param name="errorMessage"></param>
        /// <param name="fieldName"></param>
        /// <returns></returns>
        public bool ValidateConstructionProgress(CS_ConstructionProgressDTO subconDTO, out string errorMessage, out string fieldName)
        {
            errorMessage = Constants.EMPTY_TEXT;
            fieldName = Constants.EMPTY_TEXT;
            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="subconDTO"></param>
        /// <returns></returns>
        public long CreateConstructionProgress(CS_ConstructionProgressDTO subconDTO)
        {
            subconDTO.Reporter = Global.Global.TitleCase(subconDTO.Reporter);
            subconDTO.Reporter = Global.Global.RemoveRedundantSpace(subconDTO.Reporter);
            return _consDAO.CreateConstructionProgress(subconDTO);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="subconID"></param>
        /// <returns></returns>
        public bool DeleteConstructionProgress(long subconID, long consID)
        {
            return _consDAO.DeleteConstructionProgress(subconID, consID);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="isactive"></param>
        /// <returns></returns>
        internal List<CS_ConstructionProgressDTO> LoadConstructionProgress(long consID)
        {
            return _consDAO.LoadConstructionProgresss(consID);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="subconDTO"></param>
        /// <returns></returns>
        internal bool UpdateConstructionProgress(CS_ConstructionProgressDTO subconDTO)
        {
            return _consDAO.UpdateConstructionProgress(subconDTO);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="subconID"></param>
        /// <returns></returns>
        internal CS_ConstructionProgressDTO GetConstructionProgressByID(long subconID)
        {
            return _consDAO.GetConstructionProgressByID(subconID);
        }
        #endregion
    }
}
